using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Rogue
{
    // A window for showing some lines of text (ie the console window)

    public class MessageWindow : TextWindow
    {
        #region Protected Member Variables
        protected List<MessageData> m_PostDamageMessages;
        protected List<MessageData> m_MessageBuffer;
        protected int m_nMaxMessageBufferSize;
        protected int m_nMessageOffset;
        protected KeyboardState m_LastKeyboardState;
        #endregion

        protected class MessageData
        {
            public string s;
            public Color color;
            public float age;

            public MessageData(string a_sMessage, Color a_Color)
            {
                s = a_sMessage;
                color = a_Color;
                age = 0.0f;
            }
        }

        public MessageWindow(
            Texture2D a_Tex,
            GraphicsDevice a_Dev,
            Point a_pPos,
            Point a_pCellMapSize,
            Point a_pCellScreenSize,
            Point a_pCharacterOffset,
            int a_nTextBufferSize
            )
            : base(a_Tex, a_Dev, a_pPos, a_pCellMapSize, a_pCellScreenSize, a_pCharacterOffset)
        {
            m_PostDamageMessages = new List<MessageData>(a_nTextBufferSize);
            m_MessageBuffer = new List<MessageData>(a_nTextBufferSize);
            m_nMaxMessageBufferSize = a_nTextBufferSize;
        }

        #region Public Commands
        public void AddPostDamageMessage(string a_sMessage, Color a_Color)
        {
            m_PostDamageMessages.Add(new MessageData(a_sMessage, a_Color));
        }

        public void ProcessPostDamageMessages()
        {
            foreach (MessageData md in m_PostDamageMessages)
                AddMessage(md.s, md.color);

            m_PostDamageMessages.Clear();
        }

        public void AddMessage(string a_sMessage, Color a_Color)
        {
            m_MessageBuffer.Add(new MessageData(a_sMessage, a_Color));
            if (m_MessageBuffer.Count > m_nMaxMessageBufferSize)
                m_MessageBuffer.RemoveAt(0);
        }
        #endregion

        #region Update
        public override void Update(GameTime dt)
        {
            KeyboardState CurrentKeyboardState = Keyboard.GetState();
            ProcessMessageWindowKeys(CurrentKeyboardState);
            m_LastKeyboardState = CurrentKeyboardState;

            for (int i = 0; i < m_MessageBuffer.Count; ++i)
            {
                m_MessageBuffer[i].age += (dt.ElapsedGameTime.Milliseconds / 1000.0f);
            }
        }

        protected void ProcessMessageWindowKeys(KeyboardState a_CurState)
        {

            #region Page Up Controls
            if (a_CurState.IsKeyDown(Keys.PageUp) && !m_LastKeyboardState.IsKeyDown(Keys.PageUp))
            {
                if ((m_nMessageOffset - Height) >= -m_MessageBuffer.Count)
                    m_nMessageOffset--;
            }
            #endregion

            #region Page Down Controls
            if (a_CurState.IsKeyDown(Keys.PageDown) && !m_LastKeyboardState.IsKeyDown(Keys.PageDown))
            {
                if (m_nMessageOffset < 0)
                {
                    m_nMessageOffset++;
                }
            }
            #endregion

            #region End Controls
            if (a_CurState.IsKeyDown(Keys.End) && !m_LastKeyboardState.IsKeyDown(Keys.End))
                m_nMessageOffset = 0;
            #endregion

        }
        #endregion

        #region Rendering Overrides
        /// <summary>
        /// Draws the message buffer to the cell window, using the specified number of lines.
        /// </summary>
        /// <param name="a_nLines">How many lines do you want to draw frop the top of the cell window?</param>
        protected void DrawMessageBuffer(int a_nLines)
        {
            if (m_MessageBuffer.Count > 0)
            {
                MessageData[] aMessages = m_MessageBuffer.ToArray();
                int nCurrentMessage = aMessages.GetLength(0) - 1;
                
                for (int y = (a_nLines - 1); y >= 0; y--)
                {
                    if ((nCurrentMessage + m_nMessageOffset >= 0) && (nCurrentMessage + m_nMessageOffset< aMessages.GetLength(0)))
                    {
                        if ((y == a_nLines - 1) && (m_nMessageOffset == 0))
                        {
                            PutString(aMessages[nCurrentMessage + m_nMessageOffset].s, 0, y, aMessages[nCurrentMessage + m_nMessageOffset].color);
                            nCurrentMessage--;
                        }
                        else
                        {
                            Color cDimmed = new Color(
                                aMessages[nCurrentMessage + m_nMessageOffset].color.R,
                                aMessages[nCurrentMessage + m_nMessageOffset].color.G,
                                aMessages[nCurrentMessage + m_nMessageOffset].color.B,
                                200
                                ); 
 
                            PutString(aMessages[nCurrentMessage + m_nMessageOffset].s, 0, y, cDimmed);
                            nCurrentMessage--;
                        }
                    }
                }
            }
        }

        public override void RenderCells()
        {
            DrawMessageBuffer(Height);  // Since this is only a message window, we want to fill it completely.

            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    m_SpriteBatch.Draw(m_Texture, GetRenderDest(x, y), GetRenderSource(x, y), m_aCellMap[x, y].ForegroundColor);
                }
            }
        }
        #endregion

    }
}
